<?php

/**
  *
  * PLUG-IN FOR NucleusCMS
  * ITEM quick edit use jQuery
  * PHP versions 4 and 5
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  * (see nucleus/documentation/index.html#license for more info)
  *
  * @author    shizuki
  * @copyright 2007 shizuki
  * @license   http://www.gnu.org/licenses/gpl.txt  GNU GENERAL PUBLIC LICENSE Version 2, June 1991
  * @version   $Id: NP_jQueryEdit.php 57 2009-03-03 17:53:55Z shizuki17xx $
  * @link      http://shizuki.kinezumi.net/
  *
  * 0.0.1      Initial version.
  * 0.0.2      Inline only version.
  * 0.0.3      Support Safari3(win) and Opera9(win).
  * 0.0.4      Fix htmlspecialchars().
  *
  **/


/**
  *
  * JSON Encode function for php4
  *
  **/
if(!function_exists('json_encode')) {
	include_once(dirname(__FILE__) . '/jqueryedit/jsphonEncoder.php');
	$GLOBALS['JSON_OBJECT'] = new Jsphon_Encoder();
	function json_encode($value)
	{
		return $GLOBALS['JSON_OBJECT']->encode($value); 
	}
}

class NP_jQueryEdit extends NucleusPlugin
{

	// {{{ function getName()

	/**
	  * Name of the plugin
	  *
	  * @return string
	  *     The name easy to understand for man of the plugin
	  **/
	function getName()
	{
		return 'Quick ITEM editor'; 
	}

	// }}}
	// {{{ function getAuthor()

	/**
	  * Author of the plugin
	  *
	  * @return string
	  *     The name of the plugin author
	  **/
	function getAuthor()
	{ 
		return 'shizuki'; 
	}

	// }}}
	// {{{ function getURL()

	/**
	  * URL of the site which can download a plugin
	  *
	  * @return string
	  *     URL of the site which can download a plugin
	  **/
	function getURL()
	{
		return 'http://shizuki.kinezumi.net/'; 
	}

	// }}}
	// {{{ function getVersion()

	/**
	  * Version of the plugin
	  *
	  * @access public
	  *
	  * @return string
	  *     Version of the plugin
	  **/
	function getVersion()
	{
		return '0.0.4'; 
	}

	// }}}
	// {{{ function getDescription()

	/**
	  * Description of the plugin
	  *
	  * @return string
	  *     Description of a plugin
	  **/
	function getDescription()
	{ 
		return 'The article which is being indicated will be edited immediately.';
	}

	// }}}
	// {{{ function supportsFeature($what)

	/**
	  * Check whether the feature is being supported.
	  *
	  * @param  string
	  *     Feature name
	  *
	  * @return boolean
	  **/
	function supportsFeature($what)
	{
		switch($what){
			case 'SqlTablePrefix':
				return 1;
			default:
				return 0;
		}
	}

	// }}}
	// {{{ function init()

	/**
	  * Plugin initialize action
	  *
	  * @return void
	  **/
	function init()
	{
		$language = ereg_replace( '[\\|/]', '', getLanguageName());
		if (file_exists($this->getDirectory() . 'language/' . $language . '.php')) {
			include_once($this->getDirectory() . 'language/' . $language . '.php');
		} else {
			include_once($this->getDirectory() . 'language/english.php');
		}
	}

	// }}}
	// {{{ function getEventList()

	/**
	  * Event list plugin exist
	  *
	  * @return array
	  *     exist events
	  **/
	function getEventList()
	{
		return array(
					 'PreSkinParse',
					 'PreItem',
					 'AdminPrePageFoot',
					 'AdminPrePageHead',
					);
	}

	// }}}
	// {{{ function event_AdminPrePageHead($data)

	/**
	  * Nucleus adminarea's extra header
	  *
	  * @access public
	  *
	  * @param  array
	  *     extrahead(reference) : Between "<head>" and "</head>" adding code
	  *     extrahead(value)     : action type
	  *
	  * @return void
	  **/
	function event_AdminPrePageHead($data)
	{
		if ($data['action'] != 'templateedit' && $data['action'] != 'templateupdate') return;
		$templateId   = intRequestVar('templateid');
		$tempalteName = TEMPLATE::getNameFromId($templateId);
		$tempalteDesc = TEMPLATE::getDesc($templateId);
		if (strpos(strtolower($tempalteName), 'npjqe') === false &&
			strpos(strtolower($tempalteDesc), 'npjqe') === false) {
				return;
		}
		$data['extrahead'] .= '<script type="text/javascript" src="' . $this->getAdminURL() . 'javascript/jquery-1.2.1.pack.js">'
							. '</script>';
	}

	// }}}
	// {{{ function event_AdminPrePageFoot()

	/**
	  * Nucleus adminarea's extra footer
	  *
	  * @access public
	  *
	  * @param  array
	  *     extrahead(value) : action type
	  *
	  * @return void
	  **/
	function event_AdminPrePageFoot($data)
	{
		if ($data['action'] != 'templateedit' && $data['action'] != 'templateupdate') return;
		$templateId   = intRequestVar('templateid');
		$tempalteName = TEMPLATE::getNameFromId($templateId);
		$tempalteDesc = TEMPLATE::getDesc($templateId);
		if (strpos(strtolower($tempalteName), 'npjqe') === false &&
			strpos(strtolower($tempalteDesc), 'npjqe') === false) {
				return;
		}
		$title = _NP_JQE_TEMPLATES;
		$add   = _NP_JQE_ADD;
		$edit  = _NP_JQE_EDIT;
		echo <<<___SCRIPT___

<script type="text/javascript">
$('table').ready(function(){
	var row = $('tr').get();
	var title = $(row[5]).children();
	title.text('{$title}');
	for (var i=6;i<row.length-2;i++) {
		var tcol = $(row[i]).children();
		var txta = $(tcol[1]).children();
		if ($(txta[0]).attr('name') == 'ITEM') {
			$(tcol[0]).text('{$add}');
			$(txta[0]).attr('rows', '15')
		} else if ($(txta[0]).attr('name') == 'COMMENTS_BODY') {
			$(tcol[0]).text('{$edit}');
			$(txta[0]).attr('rows', '15')
		} else {
			$(row[i]).remove();
		}
	}
});
</script>

___SCRIPT___;
	}

	// }}}
	// {{{ function doSkinVar($skinType, $mode = 'inline', $jQeryComponents = '1/1/1/1', $template = '')

	/**
	  * Include javascript files and print javascript code
	  *
	  * @param  string
	  *     Skin type
	  * @param  string
	  *     jQuery components load settings
	  *     Main script/jTagEditor/ThickBox/jQueryForm
	  *                        or
	  *     Bookmarklet settings
	  *     width/height/title/link text
	  * @param  string
	  *     Bookmarklet template name
	  *
	  * @return void
	  **/
	function doSkinVar($skinType, $mode = 'inline', $jQeryComponents = '1/1/1/1', $template = '')
	{
		global $CONF, $member, $blogid, $itemid;
		if (!$member->isLoggedIn()) return;
		list($jqm, $jte, $tbx, $frm) = explode('/', $jQeryComponents);
		$actParsed = parse_url($CONF['ActionURL']);
		$blgParsed = parse_url(createBlogIDLink($blogid));
		$actionURL = ($actParsed['host'] == $blgParsed['host']) ?
			$CONF['ActionURL'] :
			createBlogIDLink($blogid);
		$output = '';
		switch ($mode) {
			case 'bookmarklet':
				if (!$member->teamRights($blogId)) return;
				if (empty($template)) {
					$output .= $this->includeJQuery($jqm);
					$output .= $this->includeThickBox($tbx);
				} else {
					$linkPrm = array(
						'mode' => 'add',
						'url'  => htmlspecialchars($actionURL, ENT_QUOTES, _CHARSET),
						'bid'  => intval($blogid),
						'iid'  => intval($itemid)
					);
					$output .= $this->getBookmarkletLink($linkPrm, $jQeryComponents, $template);
				}
				break;
			case 'inline':
				if ($skinType != 'item' || !$member->canAlterItem($itemid)) return;
				$output .= $this->includeJQuery($jqm);
				$output .= $this->includeJTagEditor($jte);
				$output .= $this->includeJQueryForm($frm);
				$output .= $this->includeEditScript();
				$output .= $this->includeInlineScript($itemid, $actionURL);
				break;
			case 'all':
				if (!$member->teamRights($blogId)) return;
				$output .= $this->includeJQuery($jqm);
				if ($skinType == 'item' && $member->canAlterItem($itemid)) {
					$output .= $this->includeJTagEditor($jte);
					$output .= $this->includeJQueryForm($frm);
					$output .= $this->includeEditScript();
					$output .= $this->includeInlineScript($itemid, $actionURL);
				}
				$output .= $this->includeThickBox($tbx);
				break;
			default:
				$output .= '';
				break;
		}
		echo $output;
	}

	// }}}
	// {{{ function includeJQuery($allow)

	/**
	  * get include jQuery code
	  *
	  * @param  boolean
	  *     is need jQuery include code ?
	  *
	  * @return string
	  *     include javascript HTML code
	  **/
	function includeJQuery($allow)
	{
		if (!intval($allow)) return '';
		$aURL = htmlspecialchars($this->getAdminURL(), ENT_QUOTES, _CHARSET);
		$data = '<script type="text/javascript" '
			  . 'src="' . $aURL . 'javascript/jquery-1.2.1.pack.js">'
			  . "</script>\n";
		return $data;
	}

	// }}}
	// {{{ function includeJTagEditor($allow)

	/**
	  * get include jQuery plugin code
	  *
	  * @param  boolean
	  *     is need jTagEditor include code ?
	  *
	  * @return string
	  *     include javascript HTML code
	  **/
	function includeJTagEditor($allow)
	{
		if (!intval($allow)) return '';
		$aURL = htmlspecialchars($this->getAdminURL(), ENT_QUOTES, _CHARSET);
		$data = '<script type="text/javascript" '
			  . 'src="' . $aURL . 'javascript/jtageditor.js">'
			  . "</script>\n"
			  . '<link type="text/css" '
			  . 'rel="stylesheet" '
			  . 'href="' . $aURL . 'styles/jtageditorHtml.css" '
			  . 'media="print, projection, screen" ' . "/>\n";
		return $data;
	}

	// }}}
	// {{{ function includeJQueryForm($allow)

	/**
	  * get include jQuery plugin code
	  *
	  * @param  boolean
	  *     is need jQueryForm include code ?
	  *
	  * @return string
	  *     include javascript HTML code
	  **/
	function includeJQueryForm($allow)
	{
		if (!intval($allow)) return '';
		$aURL = htmlspecialchars($this->getAdminURL(), ENT_QUOTES, _CHARSET);
		$data = '<script type="text/javascript" '
			  . 'src="' . $aURL . 'javascript/jquery.form.js">'
			  . "</script>\n";
		return $data;
	}

	// }}}
	// {{{ function includeThickBox($allow)

	/**
	  * get include jQuery plugin code
	  *
	  * @param  boolean
	  *     is need ThickBox include code ?
	  *
	  * @return string
	  *     include javascript HTML code
	  **/
	function includeThickBox($allow)
	{
		if (!intval($allow)) return '';
		$aURL = htmlspecialchars($this->getAdminURL(), ENT_QUOTES, _CHARSET);
		$data = '<script type="text/javascript" '
			  . 'src="' . $aURL . 'javascript/thickbox-compressed.js">'
			  . "</script>\n"
			  . '<link type="text/css" '
			  . 'rel="stylesheet" '
			  . 'href="' . $aURL . 'styles/thickbox.css" '
			  . 'media="print, projection, screen" ' . "/>\n"
			  . '<script type="text/javascript">'
			  . "\ttb_pathToImage = '{$aURL}images/loadingAnimation.gif';"
			  . "</script>\n";
		return $data;
	}

	// }}}
	// {{{ function includeEditScript()

	/**
	  * get include inlineEditScript code
	  *
	  * @return string
	  *     include javascript HTML code
	  **/
	function includeEditScript()
	{
		$aURL = htmlspecialchars($this->getAdminURL(), ENT_QUOTES, _CHARSET);
		$data = '<script type="text/javascript" '
			  . 'src="' . $aURL . 'javascript/NP_jQueryEdit.js">'
			  . "</script>\n";
		return $data;
	}

	// }}}
	// {{{ function includeEditScript($itemid, $actionURL)

	/**
	  * get include inlineEditScript code
	  *
	  * @param intger
	  *     editing item ID
	  * @param string
	  *     URL of AJAX sending
	  *
	  * @return string
	  *     include javascript code
	  **/
	function includeInlineScript($itemid, $actionURL)
	{
		global $CONF, $manager;
		$domain = (!empty($CONF['CookieDomain'])) ? trim($CONF['CookieDomain'], '.') : "";
		$item   =& $manager->getItem($itemid, 0, 0);
		$author = $item['authorid'];
		$data = <<<INLINESCRIPT

<script type="text/javascript">
	$(function() {
//		var title = $("#NPjQEitemTitle");
		var body = $("#NPjQEitemBody");
		var more = $("#NPjQEitemMore");
//		title.dblclick(function(){insertForm();});
		body.dblclick(function(){insertForm();});
		more.dblclick(function(){insertForm();});
		body.before('<span id="NPjQEPreviewLabel"></span>');
		setActionURL('{$actionURL}');
		setCurrentItemID({$itemid});
		setMediaPopupURL('{$CONF['AdminURL']}');
		setScriptDomain('{$domain}');
		setAuthorId('{$author}');
	});
</script>

INLINESCRIPT;
		return $data;
	}

	// }}}
	// {{{ function getBookmarkletLink($actionURL, $popupParams, $template)

	/**
	  * get link for bookmarklet as add new item or edit item
	  *
	  * @param array
	  *     mode : strings
	  *         bookmarklet mode
	  *     url  : strings
	  *         URL of plugin action
	  *     bid  : intger
	  *         blog ID when add mode
	  *     iid  : intger
	  *         item ID when edit mode
	  *
	  * @return string
	  *     link for popup window
	  **/
	function getBookmarkletLink($linkPrm, $popupParams, $template)
	{
		list($width, $height, $title, $label) = explode('/', $popupParams);
		extract($linkPrm);
		$width  = (is_numeric($width)  && $width  > 2)  ? intval($width)  : 600;
		$height = (is_numeric($height) && $height > 2)  ? intval($height) : 450;
		$title  = (!empty($title) && is_string($title)) ? "title=\"{$title}\"" : '';
		$label  = (!empty($label) && is_string($label)) ? $label : '[Edit]';
		$title  = htmlspecialchars($title, ENT_NOQUOTES, _CHARSET);
		$label  = htmlspecialchars($label, ENT_NOQUOTES, _CHARSET);
		$link   = "<a href=\"{$url}?"
				. "action=plugin&amp;"
				. "name=jQueryEdit&amp;"
				. "type=bookmarklet&amp;"
				. "template={$template}&amp;"
				. "mode={$mode}&amp;"
				. "blogid={$bid}&amp;"
				. "itemid={$iid}&amp;"
				. "height={$height}&amp;"
				. "width={$width}\""
				. "{$title} class=\"thickbox\">{$label}</a>\n";
		return $link;
	}

	// }}}
	// {{{ function doTemplateVar(&$item)

	/**
	  * get link for bookmarklet as edit item
	  *
	  * @param  object
	  *     reference ITEM object
	  *
	  * @return void
	  **/
	function doTemplateVar(&$item, $popupParams, $template = 'NPjQE/bookmarklet')
	{
		global $CONF, $member, $currentTemplateName;
		$itemid = intval($item->itemid);
		$blogid = intval(getBlogIDFromItemID($itemid));
		if ($this->skinType != 'item' || !$member->isLoggedIn()) return;
		if (!$member->canAlterItem($itemid)) return;

		$template = TEMPLATE::read($currentTemplateName);
//		$inBody   = (strpos($template['ITEM'], '<%jQueryEdit') !== false);
		if (strpos($template['EDITLINK'], '<%jQueryEdit') === false) return;

		$actParsed = parse_url($CONF['ActionURL']);
		$blgParsed = parse_url(createBlogIDLink($blogid));
		$actionURL = ($actParsed['host'] == $blgParsed['host']) ?
			$CONF['ActionURL'] :
			createBlogIDLink($blogid);
		$linkPrm = array(
			'mode' => 'edit',
			'url'  => htmlspecialchars($actionURL, ENT_QUOTES, _CHARSET),
			'bid'  => intval($blogid),
			'iid'  => intval($itemid)
		);
		$link = $this->getBookmarkletLink($linkPrm, $popupParams, $template);
	}

	// }}}
	// {{{ function event_PreItem($data)

	/**
	  * Add DOM elements
	  *
	  * @param  array
	  *     item : reference ITEM object
	  *     blog : reference BLOG object
	  *
	  * @return void
	  **/
	function event_PreItem($data)
	{
		global $member, $currentTemplateName;
		$this->currentItem = $data['item'];
		if ($this->skinType != 'item' || !$member->isLoggedIn()) return;
		if (!$member->canAlterItem(intval($data['item']->itemid))) return;
//		$data['item']->title = '<span id="NPjQEitemTitle" class="NPjQEitemEntry">' . $data['item']->title . '</span>';
		$data['item']->body = '<span id="NPjQEitemBody" class="NPjQEitemEntry">' . $data['item']->body . '</span>';
		$data['item']->more = '<span id="NPjQEitemMore" class="NPjQEitemEntry">' . $data['item']->more . '</span>';
?>
<script type="text/javascript">
	setCurrentTemplateName("<?php echo $currentTemplateName; ?>");
</script>
<?php
	}


	// }}}
	// {{{ function event_PreSkinParse($data)

	/**
	  * Get current skin type
	  *
	  * @param  array
	  *     skin     : reference SKIN         object
	  *     type     : value     skintype     string
	  *     contents : reference skincontents object
	  *
	  * @return void
	  **/
	function event_PreSkinParse($data)
	{
		global $member, $itemid;
		if ($data['type'] != 'item' || !$member->isLoggedIn()) return;
		if (!$member->canAlterItem(intval($itemid))) return;
		$this->skinType = $data['type'];
	}

	// }}}
	// {{{ function doAction($actionType)

	/**
	  * Response to AJAX XMLHttpRequest
	  *
	  * @param string value
	  *     request action type
	  *
	  * @return void
	  **/
	function doAction($actionType)
	{
		global $member, $manager;
		$aActionsNotToCheck = array(
			'',
			'jtageditor',
			'inputvalue',
			'formresults',
			'addmedia',
		);
		$actionType = strtolower($actionType);
		if (!in_array($actionType, $aActionsNotToCheck)) {
			if (!$manager->checkTicket()) return _ERROR_BADTICKET;
		}
		$itemid = intRequestVar('item');
		$blogid = getBlogIDFromItemID($itemid);
		if (!$member->isLoggedIn()) return;
		$currentItem =& $manager->getItem($itemid, 0, 0);
		$currentBlog =& $manager->getBlog($blogid);
		switch ($actionType) {
			case 'addmedia':
				global $DIR_NUCLEUS;
				$_REQUEST['action'] = 'selectmedia';
				$_GET['action'] = 'selectmedia';
				include($DIR_NUCLEUS . 'media.php');
				break;
			case 'jtageditor':
				$tagSet = file_get_contents($this->getDirectory() . 'javascript/jtageditor_htmltags.js');
				echo $tagSet;
				break;
			case 'inputvalue':
				if (!$member->canAlterItem($itemid)) return;
				echo $this->getInlineInputValue($currentBlog, $currentItem);
				break;
			case 'formresults':
				if (!$member->canAlterItem($itemid)) return;
				$title = postVar('NPjQEinputTitle');
				$body  = postVar('NPjQEinputBody');
				$more  = postVar('NPjQEinputMore');
				if ($currentBlog->convertBreaks()) {
					$body = addBreaks($body);
					$more = addBreaks($more);
				}
				$parseData = array(
					'template' => TEMPLATE::read(postVar('template')),
					'blog'     => &$currentBlog,
					'item'     => (object)$currentItem
				);
				$parseData['item']->body = $body;
				$parseData['item']->more = $more;
				ob_start();
				$manager->notify('PreItem', array('blog' => &$currentBlog, 'item' => &$parseData['item']));
				ob_end_clean();
				ob_start();
				$this->parseContent($parseData, &$parseData['item']->body);
				$body = $this->stripNPjQETag(ob_get_contents());
				ob_end_clean();
				ob_start();
				$this->parseContent($parseData, &$parseData['item']->more);
				$more = $this->stripNPjQETag(ob_get_contents());
				ob_end_clean();
				ob_start();
				$manager->notify('PostItem', array('blog' => &$currentBlog, 'item' => &$parseData['item']));
				ob_end_clean();
				$data = array(
					'NPjQEinputTitle' => $title,
					'NPjQEinputBody'  => $body,
					'NPjQEinputMore'  => $more
				);
				if (postVar('preview')) {
					$data['preview'] = 'Preview!';
					$commit = false;
				} else {
					$commit = true;
				}
				echo json_encode($data);
				if ($commit) {
					$cid = $parseData['item']->catid;
//					$ttl = postVar('NPjQEinputTitle');
					$ttl = $parseData['item']->title;
					$cls = $parseData['item']->closed;
					$bdy = postVar('NPjQEinputBody');
					$mor = postVar('NPjQEinputMore');
					ITEM::update($itemid, $cid, $ttl, $bdy, $mor, $cls, 0, 1, 0);
				}
				break;
			default:
				exit;
		}
		exit;
	}

	// }}}
	// {{{ function parseContent(&$parseData, &$data)

	/**
	  * Get parsed content for preview
	  *
	  * @param array reference
	  *     blog     : object blog settings
	  *     template : array template value
	  *     item     : object item data
	  * @param string reference
	  *     editing contents value
	  *
	  * @return void
	  **/
	function parseContent(&$parseData, &$data)
	{
		$actions =& new BODYACTIONS($parseData['blog']);
		$parser  =& new PARSER($actions->getDefinedActions(), $actions);
		$actions->setTemplate($parseData['template']);
		$actions->setCurrentItem($parseData['item']);
		$parser->parse($actions->highlight($data));
	}

	// }}}
	// {{{ function stripNPjQETag($html)

	/**
	  * Strip editor tag
	  *
	  * @param string value
	  *     editing contents value
	  *
	  * @return string
	  *     editing contents value of tag striped
	  **/
	function stripNPjQETag($html)
	{
		$html = preg_replace('!^<span id="NPjQEitem.*?">(.*?)</span>$!is', '$1', $html) ;
		return $html ;
	}

	// }}}
	// {{{ function getInlineInputValue($blog, $item)

	/**
	  * Strip editor tag
	  *
	  * @param object value
	  *     Blog object, edit item
	  * @param array value
	  *     Item array for edit
	  *
	  * @return string
	  *     JSON data of edit item
	  **/
	function getInlineInputValue($blog, $item)
	{
		if ($blog->convertBreaks()) {
			$body = removeBreaks($item['body']);
			$more = removeBreaks($item['more']);
		} else {
			$body = $item['body'];
			$more = $item['more'];
		}
		$data = array(
			'NPjQEinputTitle' => htmlspecialchars($item['title'], ENT_QUOTES, _CHARSET),
			'NPjQEinputBody'  => htmlspecialchars($body, ENT_QUOTES, _CHARSET),
			'NPjQEinputMore'  => htmlspecialchars($more, ENT_QUOTES, _CHARSET)
		);
		return json_encode($data);
	}

	// }}}















}



